<?php
// app/api/service/payment/WechatPayment.php
declare(strict_types=1);

namespace app\api\service\payment;

use app\admin\logic\system\SystemConfigLogic;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\ServiceNotFoundException;

class WechatPayment extends AbstractPayment
{
    private array $config;

    public function __construct($orderModel)
    {
        $this->orderModel = $orderModel;
        $logic = new SystemConfigLogic();
        $wechat_payConfig = $logic->getConfig('wechat_pay')['value'];
        $miniappConfig = $logic->getConfig('miniapp')['value'];
        $wechatConfig = $logic->getConfig('wechat')['value'];
        // 初始化微信支付配置
        $this->config = [
            'wechat' => [
                'default' => [
                    // 必填-商户号，服务商模式下为服务商商户号
                    'mch_id' => $wechat_payConfig['merchantId'],
                    // 必填-商户秘钥
                    'mch_secret_key' => $wechat_payConfig['apiKey'],
                    // 必填-商户私钥 字符串或路径
                    'mch_secret_cert' => convert_str_to_pem($wechat_payConfig['certificateKey']),
                    // 必填-商户公钥证书路径
                    'mch_public_cert_path' => convert_str_to_pem($wechat_payConfig['certificate']),
                    // 必填
                    'notify_url' => $wechat_payConfig['authDirectory'],
                    'mini_app_id' => $miniappConfig['app_id'],
                    'mp_app_id' => $wechatConfig['app_id']
                ],
            ],
        ];
        // 配置 Pay
        Pay::config($this->config);
    }

    /**
     * 处理微信支付
     * @param array $order 订单信息
     * @return array|false
     */
    public function pay(array $order)
    {
        try {
            $this->validateOrder($order);
            // 构建支付参数
            $params = [
                'out_trade_no' => $order['order_no'],
                'description' => $order['body'] ?? '商品购买',
                'amount' => [
                    'total' => intval($order['total_amount'] * 100), // 转换为分
                    'currency' => 'CNY',
                ],
            ];
            // 根据场景选择支付方式
            $payScene = $order['pay_scene'] ?? 'mp';

            switch ($payScene) {
                case 'mp': //公众号
                    if (empty($order['openid'])) {
                        throw new \Exception('公众号支付必须传入openid');
                    }
                    $params['payer'] = [
                        'openid' => $order['openid']
                    ];
                    $result = Pay::wechat()->mp($params); // 公众号支付
                    break;
                case 'mini': // 小程序
                    if (empty($order['openid'])) {
                        throw new \Exception('小程序支付必须传入openid');
                    }
                    $params['payer'] = [
                        'openid' => $order['openid']
                    ];
                    $result = Pay::wechat()->mini($params); // 小程序支付
                    break;
                case 'app': // APP支付
                    $result = Pay::wechat()->app($params); // APP支付
                    break;
                case 'scan': // 扫码支付
                    $result = Pay::wechat()->scan($params); // 扫码支付
                    break;
                case 'h5': // H5支付
                    $params['scene_info'] = [
                        'payer_client_ip' => $order['client_ip'] ?? request()->getRealIp($safe_mode=true),
                        'h5_info' => [
                            'type' => 'Wap',
                        ]
                    ];
                    $result = Pay::wechat()->h5($params); // H5支付
                    break;
                default:
                    throw new \Exception('不支持的支付场景');
            }
            return [
                'pay_status' => 'success',
                'pay_data' => $result
            ];
        } catch (\Exception $e) {
            return $this->setError('支付失败：' . $e->getMessage());
        }
    }

    /**
     * 验证订单参数
     * @param array $order
     */
    private function validateOrder(array $order): void
    {
        if (empty($order['order_no'])) {
            throw new \Exception('订单号不能为空');
        }
        if (empty($order['total_amount']) || $order['total_amount'] <= 0) {
            throw new \Exception('订单金额必须大于0');
        }
        // 验证支付场景
        $validScenes = ['mp', 'mini', 'app', 'scan', 'h5'];
        if (!empty($order['pay_scene']) && !in_array($order['pay_scene'], $validScenes)) {
            throw new \Exception('无效的支付场景');
        }
    }

    /**
     * 处理支付回调
     * @return array
     */
    public function handleNotify($params): array
    {
        try {
            $result = Pay::wechat()->callback($params);
            // 判断支付状态
            if ($result->event_type === 'TRANSACTION.SUCCESS') {
                // 更新订单状态等操作
                return [
                    'code' => 'SUCCESS',
                    'message' => '支付成功',
                    'data' => $result->toArray()
                ];
            }
            return [
                'code' => 'FAIL',
                'message' => '支付失败',
                'data' => $result->toArray()
            ];
        } catch (\Exception $e) {
            return [
                'code' => 'ERROR',
                'message' => $e->getMessage()
            ];
        }
    }


    /**
     * 确认回调
     */
    public function confirmNotify()
    {
        return Pay::wechat()->success();
    }
}